package com.zhou.jianzhi.controller.web;

import com.zhou.jianzhi.common.AjaxResult;
import com.zhou.jianzhi.entity.dto.AliyunOssDTO;
import com.zhou.jianzhi.entity.po.AliyunOss;
import com.zhou.jianzhi.service.IAliyunOssService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;

/**
 * 文件上传控制器
 * 
 * @author claude
 * @date 2023-03-09
 */
@RestController
@RequestMapping("/file")
public class FileUploadController {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;
    
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;
    
    @Value("${aliyun.oss.region}")
    private String region;
    
    @Value("${aliyun.oss.bucket}")
    private String bucket;
    
    @Value("${file.upload.path}")
    private String uploadPath;
    
    @Autowired
    private IAliyunOssService aliyunOssService;
    
    /**
     * 文件上传
     * 
     * @param file 文件
     * @param filePath 文件存储路径
     * @param source 来源
     * @param used 用途
     * @param jobseekerId 求职者ID
     * @param recruitUnitId 招聘单位ID
     * @return 上传结果
     * @throws Exception 异常
     */
    @PostMapping("/upload")
    public AjaxResult upload(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "filePath", required = false) String filePath,
            @RequestParam(value = "source", required = false) String source,
            @RequestParam(value = "used", required = false) Integer used,
            @RequestParam(value = "jobseekerId", required = false) Integer jobseekerId,
            @RequestParam(value = "recruitUnitId", required = false) Integer recruitUnitId) throws Exception {
        
        if (file.isEmpty()) {
            return AjaxResult.error("上传文件不能为空");
        }
        
        // 获取文件名和后缀
        String fileName = file.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        String uid = UUID.randomUUID().toString().replaceAll("-", "");
        String objectName = (filePath == null ? "" : filePath) + uid + "." + suffix;
        
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        
        try {
            // 上传文件到OSS
            ossClient.putObject(bucket, objectName, file.getInputStream());
            
            // 保存文件信息到数据库
            AliyunOssDTO aliyunOssDTO = new AliyunOssDTO();
            String fileNameWithoutSuffix = fileName.substring(0, fileName.lastIndexOf("."));
            aliyunOssDTO.setFileName(fileNameWithoutSuffix);
            aliyunOssDTO.setFilePath(objectName);
            aliyunOssDTO.setType(suffix);
            aliyunOssDTO.setSource(source);
            aliyunOssDTO.setUsed(used);
            aliyunOssDTO.setJobseekerId(jobseekerId);
            aliyunOssDTO.setRecruitUnitId(recruitUnitId);
            
            // 保存到数据库
            AjaxResult dbResult = aliyunOssService.addAliyunOss(aliyunOssDTO);
            
            // 生成临时访问URL
            Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000); // 1小时后过期
            String url = ossClient.generatePresignedUrl(bucket, objectName, expiration).toString();
            
            // 返回文件路径等信息
            Map<String, Object> data = new HashMap<>();
            data.put("fileName", fileNameWithoutSuffix);
            data.put("filePath", objectName);
            data.put("type", suffix);
            data.put("id", dbResult.get("data"));
            data.put("url", url);
            
            return AjaxResult.success("文件上传成功", data);
        } catch (Exception e) {
            return AjaxResult.error("文件上传失败: " + e.getMessage());
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
    }
    
    /**
     * 批量上传文件
     */
    @PostMapping("/batchUpload")
    public AjaxResult batchUpload(
            @RequestParam("files") MultipartFile[] files,
            @RequestParam(value = "filePath", required = false) String filePath,
            @RequestParam(value = "source", required = false) String source,
            @RequestParam(value = "used", required = false) Integer used,
            @RequestParam(value = "jobseekerId", required = false) Integer jobseekerId,
            @RequestParam(value = "recruitUnitId", required = false) Integer recruitUnitId) throws Exception {
        
        if (files == null || files.length == 0) {
            return AjaxResult.error("上传文件不能为空");
        }
        
        List<Map<String, Object>> uploadResults = new ArrayList<>();
        List<AliyunOssDTO> aliyunOssDTOList = new ArrayList<>();
        
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        
        try {
            for (MultipartFile file : files) {
                if (file.isEmpty()) {
                    continue;
                }
                
                // 获取文件名和后缀
                String fileName = file.getOriginalFilename();
                String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
                String uid = UUID.randomUUID().toString().replaceAll("-", "");
                String objectName = (filePath == null ? "" : filePath) + uid + "." + suffix;
                
                // 上传文件到OSS
                ossClient.putObject(bucket, objectName, file.getInputStream());
                
                // 准备保存文件信息到数据库
                AliyunOssDTO aliyunOssDTO = new AliyunOssDTO();
                String fileNameWithoutSuffix = fileName.substring(0, fileName.lastIndexOf("."));
                aliyunOssDTO.setFileName(fileNameWithoutSuffix);
                aliyunOssDTO.setFilePath(objectName);
                aliyunOssDTO.setType(suffix);
                aliyunOssDTO.setSource(source);
                aliyunOssDTO.setUsed(used);
                aliyunOssDTO.setJobseekerId(jobseekerId);
                aliyunOssDTO.setRecruitUnitId(recruitUnitId);
                
                aliyunOssDTOList.add(aliyunOssDTO);
                
                // 生成临时访问URL
                Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000); // 1小时后过期
                String url = ossClient.generatePresignedUrl(bucket, objectName, expiration).toString();
                
                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("fileName", fileNameWithoutSuffix);
                fileInfo.put("filePath", objectName);
                fileInfo.put("type", suffix);
                fileInfo.put("url", url);
                
                uploadResults.add(fileInfo);
            }
            
            // 批量保存到数据库
            aliyunOssService.addAliyunOssList(aliyunOssDTOList);
            
            return AjaxResult.success("文件批量上传成功", uploadResults);
        } catch (Exception e) {
            return AjaxResult.error("文件批量上传失败: " + e.getMessage());
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
    }
    
    /**
     * 文件下载 - 重定向到OSS URL
     * 
     * @param id 文件ID
     * @param response HTTP响应
     * @throws Exception 异常
     */
    @GetMapping("/download/{id}")
    public void download(@PathVariable Integer id, HttpServletResponse response) throws Exception {
        AjaxResult result = aliyunOssService.selectAliyunOssById(id);
        if (result.get("code").equals(200)) {
            AliyunOss aliyunOss = (AliyunOss) result.get("data");
            if (aliyunOss != null) {
                String filePath = aliyunOss.getFilePath();
                String fileName = aliyunOss.getFileName() + "." + aliyunOss.getType();
                
                // 生成OSS临时访问URL
                OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
                try {
                    // 生成文件下载URL（可选：设置过期时间）
                    Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000); // 1小时后过期
                    String url = ossClient.generatePresignedUrl(bucket, filePath, expiration).toString();
                    
                    // 重定向到OSS文件URL
                    response.sendRedirect(url);
                } catch (Exception e) {
                    throw new RuntimeException("文件下载失败: " + e.getMessage());
                } finally {
                    ossClient.shutdown();
                }
            } else {
                throw new RuntimeException("文件信息不存在");
            }
        } else {
            throw new RuntimeException("文件信息获取失败");
        }
    }
    
    /**
     * 文件预览 - 返回OSS文件URL
     * 
     * @param id 文件ID
     * @return 文件URL
     * @throws Exception 异常
     */
    @GetMapping("/view/{id}")
    public AjaxResult viewFile(@PathVariable Integer id) throws Exception {
        AjaxResult result = aliyunOssService.selectAliyunOssById(id);
        if (result.get("code").equals(200)) {
            AliyunOss aliyunOss = (AliyunOss) result.get("data");
            if (aliyunOss != null) {
                String filePath = aliyunOss.getFilePath();
                
                // 生成OSS临时访问URL
                OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
                try {
                    // 生成文件预览URL（可选：设置过期时间）
                    Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000); // 1小时后过期
                    String url = ossClient.generatePresignedUrl(bucket, filePath, expiration).toString();
                    
                    Map<String, Object> data = new HashMap<>();
                    data.put("url", url);
                    data.put("fileName", aliyunOss.getFileName());
                    data.put("fileType", aliyunOss.getType());
                    
                    return AjaxResult.success(data);
                } catch (Exception e) {
                    return AjaxResult.error("获取文件预览URL失败: " + e.getMessage());
                } finally {
                    ossClient.shutdown();
                }
            } else {
                return AjaxResult.error("文件信息不存在");
            }
        } else {
            return AjaxResult.error("文件信息获取失败");
        }
    }
    
    /**
     * 获取文件内容类型
     * 
     * @param fileType 文件类型（扩展名）
     * @return 内容类型
     */
    private String getContentType(String fileType) {
        if (fileType == null) {
            return MediaType.APPLICATION_OCTET_STREAM_VALUE;
        }
        
        switch (fileType.toLowerCase()) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "pdf":
                return "application/pdf";
            case "doc":
                return "application/msword";
            case "docx":
                return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "xls":
                return "application/vnd.ms-excel";
            case "xlsx":
                return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "ppt":
                return "application/vnd.ms-powerpoint";
            case "pptx":
                return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
            case "txt":
                return "text/plain";
            case "html":
            case "htm":
                return "text/html";
            case "xml":
                return "application/xml";
            case "json":
                return "application/json";
            default:
                return MediaType.APPLICATION_OCTET_STREAM_VALUE;
        }
    }
    
    /**
     * 判断文件类型是否可以在浏览器中直接查看
     * 
     * @param fileType 文件类型（扩展名）
     * @return 是否可以在浏览器中查看
     */
    private boolean isViewableInBrowser(String fileType) {
        if (fileType == null) {
            return false;
        }
        
        switch (fileType.toLowerCase()) {
            case "jpg":
            case "jpeg":
            case "png":
            case "gif":
            case "pdf":
            case "txt":
            case "html":
            case "htm":
                return true;
            default:
                return false;
        }
    }
} 